// Fill out your copyright notice in the Description page of Project Settings.


#include "Component/Invisible.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Materials/MaterialInstanceDynamic.h"

// Sets default values for this component's properties
UInvisible::UInvisible()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = false;
	OnceStart = true;
	OnceEnd = true;
	DissolveSpeed = 0.001f;
	CurrentValue = 0.f;
	// ...
}


// Called when the game starts
void UInvisible::BeginPlay()
{
	Super::BeginPlay();
	
}

void UInvisible::ActivateAbility(UMaterialInterface* SourceMaterial,const TArray<FName> LocalParameterName) {
	ParameterName = LocalParameterName;
	Character = Cast<ACharacter>(GetOwner());
	check(Character);
	if (!IsInvisibleActive) {
		if (IsDissolving|| !OnceStart) return;
		OnceStart = false;
		IsInvisibleActive = true;
		OrignalMaterialArray = Character->GetMesh()->GetMaterials();
		for (int32 i = 0; i < OrignalMaterialArray.Num(); ++i) {
			DynamicMaterialarray.Add(Character->GetMesh()->CreateDynamicMaterialInstance(i, SourceMaterial));
			Start();
		}
	}
	else {
		DeactivateAbility();
	}
}

void UInvisible::DeactivateAbility() {
	if (IsDissolving) return;
	if (!OnceEnd) return;
	OnceEnd = false;
	End();
}

void UInvisible::ResetDissolveStart() {
	OnceStart = true;
}

void UInvisible::ResetDissolveEnd() {
	OnceEnd = true;
}

void UInvisible::Start() {
	IsDissolving = true;
	CurrentValue = 0.f;
	FTimerDelegate RespawnDelegate = FTimerDelegate::CreateUObject(this, &UInvisible::StartDissolve);
	GetWorld()->GetTimerManager().SetTimer(StartHandle, RespawnDelegate, UGameplayStatics::GetGlobalTimeDilation(this) * DissolveSpeed, true);
}

void UInvisible::End() {
	CurrentValue = 0.f;
	FTimerDelegate RespawnDelegate = FTimerDelegate::CreateUObject(this, &UInvisible::ReverseDissolve);
	GetWorld()->GetTimerManager().SetTimer(EndHandle, RespawnDelegate, UGameplayStatics::GetGlobalTimeDilation(this) * DissolveSpeed, true);
}

void UInvisible::StartDissolve() {
	CurrentValue += DissolveSpeed;
	float MinTime, MaxTime;
	StartDissolveCurve->GetTimeRange(MinTime, MaxTime);
	if (CurrentValue >= MaxTime) {
		GetWorld()->GetTimerManager().ClearTimer(StartHandle);
		IsDissolving = false;
		ResetDissolveStart();
	}
	else {
		for (int32 i = 0; i < DynamicMaterialarray.Num(); ++i) {
			for (int32 j = 0; j < ParameterName.Num(); ++j) {
				DynamicMaterialarray[i]->SetScalarParameterValue(ParameterName[j], StartDissolveCurve->GetFloatValue(CurrentValue));
			}
		}
	}
}

void UInvisible::ReverseDissolve() {
	CurrentValue += DissolveSpeed;
	float MinTime, MaxTime;
	ReverseDissolveCurve->GetTimeRange(MinTime, MaxTime);
	if (CurrentValue >= MaxTime) {
		GetWorld()->GetTimerManager().ClearTimer(EndHandle);
		for (int32 i = 0; i < OrignalMaterialArray.Num(); ++i) {
			Character->GetMesh()->SetMaterial(i, OrignalMaterialArray[i]);
		}
		IsInvisibleActive = false;
		ResetDissolveEnd();
		OrignalMaterialArray.Empty();
		DynamicMaterialarray.Empty();
	}
	else {
		for (int32 i = 0; i < DynamicMaterialarray.Num(); ++i) {
			for (int32 j = 0; j < ParameterName.Num(); ++j) {
				DynamicMaterialarray[i]->SetScalarParameterValue(ParameterName[j], ReverseDissolveCurve->GetFloatValue(CurrentValue));
			}
		}
	}
}